Sensor Fusion for Kinetis MCUs (ISSDK/KSDK version)
main_agm01_freertos_two_tasks.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016, NXP Semiconductor, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * o Redistributions of source code must retain the above copyright notice, this list
9  * of conditions and the following disclaimer.
10  *
11  * o Redistributions in binary form must reproduce the above copyright notice, this
12  * list of conditions and the following disclaimer in the documentation and/or
13  * other materials provided with the distribution.
14  *
15  * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from this
17  * software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 /*! \file main_agm01_freertos_two_tasks.c
31  \brief FreeRTOS (two task) implementation of sensor fusion on FRDM-K64F.
32 
33  This file shows one recommended way to incorporate sensor fusion capabilities
34  into a FreeRTOS project.
35 */
36 
37 /* FreeRTOS kernel includes. */
38 #include "FreeRTOS.h"
39 #include "task.h"
40 #include "queue.h"
41 #include "timers.h"
42 #include "event_groups.h"
43 
44 // KSDK & ISSDK Headers
45 #include "fsl_debug_console.h" // KSDK header file for the debug interface
46 #include "board.h" // KSDK header file to define board configuration
47 #include "pin_mux.h" // KSDK header file for pin mux initialization functions
48 #include "clock_config.h" // KSDK header file for clock configuration
49 #include "fsl_port.h" // KSDK header file for Port I/O control
50 #include "fsl_i2c.h" // KSDK header file for I2C interfaces
51 #include "Driver_I2C_SDK2.h" // ISSDK CMSIS driver for I2C
52 #include "fxas21002.h" // register address and bit field definitions
53 #include "fxos8700.h" // register address and bit field definitions
54 
55 // Sensor Fusion Headers
56 #include "sensor_fusion.h" // top level magCal and sensor fusion interfaces
57 #include "control.h" // Command/Streaming interface - application specific
58 #include "status.h" // Sta:tus indicator interface - application specific
59 #include "drivers.h" // NXP sensor drivers OR customer-supplied drivers
60 
61 // Global data structures
62 SensorFusionGlobals sfg; ///< This is the primary sensor fusion data structure
63 ControlSubsystem controlSubsystem; ///< used for serial communications
64 StatusSubsystem statusSubsystem; ///< provides visual (usually LED) status indicator
65 PhysicalSensor sensors[2]; ///< This implementation uses two physical sensors
66 EventGroupHandle_t event_group = NULL;
67 
68 static void read_task(void *pvParameters); // FreeRTOS Task definition
69 static void fusion_task(void *pvParameters); // FreeRTOS Task definition
70 
71 /// This is a FreeRTOS (dual task) implementation of the NXP sensor fusion demo build.
72 int main(void)
73 {
74  ARM_DRIVER_I2C* I2Cdrv = &I2C_S_DRIVER_BLOCKING; // defined in the <shield>.h file
75  BOARD_InitPins(); // defined in pin_mux.c, initializes pkg pins
76  BOARD_BootClockRUN(); // defined in clock_config.c, initializes clocks
77  BOARD_InitDebugConsole(); // defined in board.c, initializes the OpenSDA port
78 
79  I2Cdrv->Initialize(NULL); // Initialize the KSDK driver for the I2C port
80 
81  I2Cdrv->Control(ARM_I2C_BUS_SPEED, ARM_I2C_BUS_SPEED_FAST); // Configure the I2C bus speed
82 
83  initializeControlPort(&controlSubsystem); // configure pins and ports for the control sub-system
84  initializeStatusSubsystem(&statusSubsystem); // configure pins and ports for the status sub-system
85  initSensorFusionGlobals(&sfg, &statusSubsystem, &controlSubsystem); // Initialize sensor fusion structures
86  // "install" the sensors we will be using
87  sfg.installSensor(&sfg, &sensors[0], FXOS8700_I2C_ADDR, 1, (void*) I2Cdrv, FXOS8700_Init, FXOS8700_Read);
88  sfg.installSensor(&sfg, &sensors[1], FXAS21002_I2C_ADDR, 1, (void*) I2Cdrv, FXAS21002_Init, FXAS21002_Read);
89  sfg.initializeFusionEngine(&sfg); // This will initialize sensors and magnetic calibration
90 
91  event_group = xEventGroupCreate();
92  xTaskCreate(read_task, "READ", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, NULL);
93  xTaskCreate(fusion_task, "FUSION", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);
94 
95  sfg.setStatus(&sfg, NORMAL); // If we got this far, let's set status state to NORMAL
96  vTaskStartScheduler(); // Start the RTOS scheduler
97  sfg.setStatus(&sfg, HARD_FAULT); // If we got this far, FreeRTOS does not have enough memory allocated
98  for (;;) ;
99 }
100 
101 static void read_task(void *pvParameters)
102 {
103  uint16_t i=0; // general counter variable
104  portTickType lastWakeTime;
105  const portTickType frequency = 1; // tick counter runs at the read rate
106  lastWakeTime = xTaskGetTickCount();
107  while (1)
108  {
109  for (i=1; i<=OVERSAMPLE_RATE; i++) {
110  vTaskDelayUntil(&lastWakeTime, frequency);
111  sfg.readSensors(&sfg, i); // Reads sensors, applies HAL and does averaging (if applicable)
112  }
113  xEventGroupSetBits(event_group, B0);
114  }
115 }
116 
117 static void fusion_task(void *pvParameters)
118 {
119  uint16_t i=0; // general counter variable
120  while (1)
121  {
122  xEventGroupWaitBits(event_group, /* The event group handle. */
123  B0, /* The bit pattern the event group is waiting for. */
124  pdTRUE, /* BIT_0 and BIT_4 will be cleared automatically. */
125  pdFALSE, /* Don't wait for both bits, either bit unblock task. */
126  portMAX_DELAY); /* Block indefinitely to wait for the condition to be met. */
127 
128  sfg.conditionSensorReadings(&sfg); // magCal is run as part of this
129  sfg.runFusion(&sfg); // Run the actual fusion algorithms
130  sfg.applyPerturbation(&sfg); // apply debug perturbation (testing only)
131 
132  sfg.loopcounter++; // The loop counter is used to "serialize" mag cal operations
133  i=i+1;
134  if (i>=4) { // Some status codes include a "blink" feature. This loop
135  i=0; // should cycle at least four times for that to operate correctly.
136  sfg.updateStatus(&sfg); // This is where pending status updates are made visible
137  }
138  sfg.queueStatus(&sfg, NORMAL); // assume NORMAL status for next pass through the loop
139  sfg.pControlSubsystem->stream(&sfg, sUARTOutputBuffer); // Send stream data to the Sensor Fusion Toolbox
140  }
141 }
142 
143 /// \endcode
void initSensorFusionGlobals(SensorFusionGlobals *sfg, StatusSubsystem *pStatusSubsystem, ControlSubsystem *pControlSubsystem)
utility function to insert default values in the top level structure
Definition: sensor_fusion.c:68
#define OVERSAMPLE_RATE
int32_t loopcounter
counter incrementing each iteration of sensor fusion (typically 25Hz)
static void read_task(void *pvParameters)
conditionSensorReadings_t * conditionSensorReadings
preprocessing step for sensor fusion
int8_t FXOS8700_Read(PhysicalSensor *sensor, SensorFusionGlobals *sfg)
void initializeStatusSubsystem(StatusSubsystem *pStatus)
initializeStatusSubsystem() should be called once at startup to initialize the data structure and to ...
Definition: status.c:185
The top level fusion structure.
streamData_t * stream
function to create packets for serial stream
Definition: control.h:73
installSensor_t * installSensor
function for installing a new sensor into t
StatusSubsystem() provides an object-like interface for communicating status to the user...
Definition: status.h:44
static void fusion_task(void *pvParameters)
readSensors_t * readSensors
read all physical sensors
struct ControlSubsystem * pControlSubsystem
initializeFusionEngine_t * initializeFusionEngine
set sensor fusion structures to initial values
StatusSubsystem statusSubsystem
provides visual (usually LED) status indicator
#define B0
Definition: sensor_fusion.h:88
updateStatus_t * updateStatus
status=next status
int8_t FXOS8700_Init(PhysicalSensor *sensor, SensorFusionGlobals *sfg)
int8_t FXAS21002_Read(PhysicalSensor *sensor, SensorFusionGlobals *sfg)
The sensor_fusion.h file implements the top level programming interface.
SensorFusionGlobals sfg
This is the primary sensor fusion data structure.
Provides function prototypes for driver level interfaces.
he ControlSubsystem encapsulates command and data streaming functions.
Definition: control.h:64
uint8_t sUARTOutputBuffer[256]
main output buffer defined in control.c
Definition: control.c:59
int main(void)
This is a FreeRTOS (dual task) implementation of the NXP sensor fusion demo build.
int8_t initializeControlPort(ControlSubsystem *pComm)
Initialize the control subsystem and all related hardware.
Definition: control.c:182
runFusion_t * runFusion
run the fusion routines
ARM_DRIVER_I2C * I2Cdrv
KSDK handle for the I2C port defined in Driver_I2C_KSDK2.c.
Non-recoverable FAULT = something went very wrong.
Application-specific status subsystem.
An instance of PhysicalSensor structure type should be allocated for each physical sensors (combo dev...
ControlSubsystem controlSubsystem
used for serial communications
PhysicalSensor sensors[2]
This implementation uses two physical sensors.
setStatus_t * queueStatus
queue status change for next regular interval
Defines control sub-system.
EventGroupHandle_t event_group
setStatus_t * setStatus
change status indicator immediately
applyPerturbation_t * applyPerturbation
apply step function for testing purposes
int8_t FXAS21002_Init(PhysicalSensor *sensor, SensorFusionGlobals *sfg)
Operation is Nominal.